﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ScintillaNet;
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Threading;

namespace SQLRefactor
{

	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{

		/// <summary>
		/// Manage the progress bar.
		/// </summary>
		internal class Progress : IProgressBar
		{
			private System.Windows.Controls.ProgressBar _progressBar;
			public Progress ( System.Windows.Controls.ProgressBar progressBar )
			{
				this._progressBar = progressBar;
			}

			#region IProgressBar Members

			public int MaxIterations
			{
				get
				{
					return (int)this._progressBar.Dispatcher.Invoke ( DispatcherPriority.Normal,
						new Func<int> ( () => Convert.ToInt32 ( this._progressBar.Maximum ) ) );
				}
				set
				{
					this._progressBar.Dispatcher.Invoke ( DispatcherPriority.Normal,
						new Action ( () => this._progressBar.Maximum = value ) );
				}
			}

			public void Reset ()
			{
				this._progressBar.Dispatcher.Invoke ( DispatcherPriority.Normal,
						new Action ( () =>
						{
							this._progressBar.Value = 0;
							this._progressBar.Visibility = Visibility.Visible;
						} ) );
			}


			public void Finish ()
			{
				this._progressBar.Dispatcher.Invoke ( DispatcherPriority.Normal,
						new Action ( () =>
						{
							this._progressBar.Visibility = Visibility.Hidden;
						} ) );
			}

			public void StepIt ()
			{
				this._progressBar.Dispatcher.Invoke ( DispatcherPriority.Normal,
						new Action ( () => this._progressBar.Value++ ) );
			}

			#endregion
		}

		public int CurrentQuery { get; set; }

		public string MasterQuery
		{
			get
			{
				return ( masterQuery.Child as Scintilla ).Text;
			}
			set
			{
				( masterQuery.Child as Scintilla ).Text = value;
			}
		}

		public string IterationQuery
		{
			get
			{
				return ( iterationQuery.Child as Scintilla ).Text;
			}
			set
			{
				( iterationQuery.Child as Scintilla ).Text = value;
			}
		}

		public MainWindow ()
		{
			InitializeComponent ();

			( masterQuery.Child as Scintilla ).ConfigurationManager.Language = "mssql";
			( iterationQuery.Child as Scintilla ).ConfigurationManager.Language = "mssql";

			_SetToolbarImage ( "SQLRefactor.openHS.png", OpenFileImage );
			_SetToolbarImage ( "SQLRefactor.saveHS.png", SaveFileImage );

			this.DataContextChanged += new DependencyPropertyChangedEventHandler ( MainWindow_DataContextChanged );
		}

		void MainWindow_DataContextChanged ( object sender, DependencyPropertyChangedEventArgs e )
		{
			if ( e.OldValue != null )
			{
				( e.OldValue as QueryManager ).PropertyChanged -= MainWindow_PropertyChanged;
			}

			( e.NewValue as QueryManager ).PropertyChanged += new PropertyChangedEventHandler ( MainWindow_PropertyChanged );
		}

		/// <summary>
		/// If the CurrentQuery changes, refresh the differences grid...
		/// TODO, work out how to do this in Binding...
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void MainWindow_PropertyChanged ( object sender, PropertyChangedEventArgs e )
		{
			if ( e.PropertyName == "CurrentQuery" )
			{
				// Now compare to the master
				var differences = (this.DataContext as QueryManager).MasterQuery.Results.Data.GetDifferences ( (this.DataContext as QueryManager).CurrentQuery.Results.Data );

				if ( differences.Count () > 0 )
				{
					// Add the columns.
					gridDifferences.Columns.Clear ();
					for ( int i = 0; i < differences.Max ( x => new[] { x.Item1.Count (), x.Item2.Count () }.Max () ); i++ )
						gridDifferences.Columns.Add ( new DataGridTextColumn { Header = "Column " + i.ToString (), Binding = new System.Windows.Data.Binding ( "[" + i.ToString () + "]" ) } );

					gridDifferences.ItemsSource = this._GetDifferences ( differences );
					gridDifferences.Visibility = System.Windows.Visibility.Visible;
				}
				else
				{
					gridDifferences.Visibility = System.Windows.Visibility.Collapsed;
				}
			}
		}

		private IEnumerable<object[]> _GetDifferences ( IEnumerable<Tuple<object[], object[]>> differences )
		{
			foreach ( var diff in differences )
			{
				yield return diff.Item1; //.Zip ( diff.Item2, (a,b) => a.ToString() + "|" + b.ToString() );
				yield return diff.Item2;
			}
		}

		private void _SetToolbarImage ( string filename, Image image )
		{
			System.IO.Stream fileStream = this.GetType ().Assembly.GetManifestResourceStream ( filename );
			if ( fileStream != null )
			{
				PngBitmapDecoder bitmapDecoder = new PngBitmapDecoder ( fileStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default );
				ImageSource imageSource = bitmapDecoder.Frames[0];
				image.Source = imageSource;
			}
		}


		private void newToolStripMenuItem_Click ( object sender, EventArgs e )
		{
			//this._data = new RefactorData ();

			//CurrentQuery = -1;
			//ShowMasterQuery ();
		}

		private void masterQuery_DataContextChanged ( object sender, DependencyPropertyChangedEventArgs e )
		{
			if ( e.Property.Name == "MasterSql" )
				MasterQuery = e.NewValue.ToString();
		}

		private void iterationQuery_DataContextChanged ( object sender, DependencyPropertyChangedEventArgs e )
		{
			if ( e.Property.Name == "CurrentQuery" )
				IterationQuery = e.NewValue.ToString ();
		}

		private void Iteration_TextChanged ( object sender, EventArgs e )
		{
			if ( !String.Equals ( ( this.DataContext as QueryManager ).IterationSql, IterationQuery ) )
			{
				( this.DataContext as QueryManager ).TouchQuery ();
				( this.DataContext as QueryManager ).IterationSql = IterationQuery;
			}
		}

		private void Master_TextChanged ( object sender, EventArgs e )
		{
			( this.DataContext as QueryManager ).MasterSql = MasterQuery;
		}

	}
}
